﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using Geotools.Geometries;

namespace AzukiMap.DataSource
{
    public class WMSRaster : RasterDataSource
    {
        /*
        Request parameter Mandatory/optional Description
        VERSION=1.3.0 M Request version.
        REQUEST=GetMap M Request name.
        LAYERS=layer_list M Comma-separated list of one or more map layers.
        STYLES=style_list M Comma-separated list of one rendering style per requested layer.
        CRS=namespace:identifier M Coordinate reference system.
        BBOX=minx,miny,maxx,maxy M Bounding box corners (lower left, upper right) in CRS units.
        WIDTH=output_width M Width in pixels of map picture.
        HEIGHT=output_height M Height in pixels of map picture.
        FORMAT=output_format M Output format of map.
        TRANSPARENT=TRUE|FALSE O Background transparency of map (default=FALSE).
        BGCOLOR=color_value O Hexadecimal red-green-blue colour value for the background color (default=0xFFFFFF).
        EXCEPTIONS=exception_format O The format in which exceptions are to be reported by the WMS (default=XML).
        TIME=time O Time value of layer desired.
        ELEVATION=elevation O Elevation of layer desired.
        Other sample dimension(s) O Value of other dimensions as appropriate.
        */

        WMSVersion _version;
        string _request;
        List<string> _layers;
        List<string> _styles;
        //string _crs;
        GTEnvelope _bbox;
        int _width;
        int _height;
        WMSImageFormat _format;
        bool _transparent;
        Color _bgcolor;
        string _exceptions;
        Dictionary<string, string> _otherParams;

        string _requestUri;
        GTEnvelope _maxExtent;
        string _title;
        string _abstruct;

        #region properties


        public WMSVersion Version
        {
            get { return _version; }
            set { _version = value; }
        }

        public string Request
        {
            get { return _request; }
            set { _request = value; }
        }

        public List<string> Layers
        {
            get { return _layers; }
            set { _layers = value; }
        }

        public List<string> Styles
        {
            get { return _styles; }
            set { _styles = value; }
        }

        /*
        // v1.3.1 uses "CRS"
        public string Crs
        {
            get { return _crs; }
            set { _crs = value; }
        }

        // v1.1 uses "SRS"
        public string Srs
        {
            get { return _crs; }
            set { _crs = value; }
        }
         */

        public GTEnvelope Bbox
        {
            get { return _bbox; }
            set { _bbox = value; }
        }

        public int Width
        {
            get { return _width; }
            set { _width = value; }
        }

        public int Height
        {
            get { return _height; }
            set { _height = value; }
        }

        public WMSImageFormat Format
        {
            get { return _format; }
            set { _format = value; }
        }

        public bool Transparent
        {
            get { return _transparent; }
            set { _transparent = value; }
        }

        public Color Bgcolor
        {
            get { return _bgcolor; }
            set { _bgcolor = value; }
        }

        public string Exceptions
        {
            get { return _exceptions; }
        }

        public Dictionary<string, string> OtherParams
        {
            get { return _otherParams; }
            set { _otherParams = value; }
        }

        public string RequestUri
        {
            get { return _requestUri; }
            set { _requestUri = value; }
        }

        public GTEnvelope MaxExtent
        {
            get { return _maxExtent; }
            set { _maxExtent = value; }
        }

        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }

        public string Abstruct
        {
            get { return _abstruct; }
            set { _abstruct = value; }
        }

        #endregion

        public WMSRaster(string name, DataTypes type, int srid, CoordinationUnits mapUnit)
            : base(name, type, srid, mapUnit)
        {
            _request = "GetMap";
            _version = WMSVersion.V1_1_1;
            _layers = new List<string>();
            _styles = new List<string>();
            _bbox = new GTEnvelope();
            _width = 0;
            _height = 0;
            _format = WMSImageFormat.PNG;
            _transparent = false;
            _bgcolor = Colors.White;
            _exceptions = "XML";
            _otherParams = new Dictionary<string, string>();
            _maxExtent = new GTEnvelope();
        }

        public Uri GetUri()
        {
            string problemParams = checkMandatoryParams();
            if ( problemParams.Length != 0 )
            {
                throw new WmsParamsNotSetException("WMS Params are not set: " + problemParams);
            }

            string uriString =
                _requestUri
                + "?VERSION=" + GetWMSVersionString(_version)
                + "&REQUEST=" + _request
                + "&LAYERS=" + CreateCommaParam(_layers)
                + "&STYLES=" + CreateCommaParam(_styles)
                + "&" + CreateCrsStr() + "=EPSG:" + _srid.ToString()
                + "&BBOX=" + CreateBboxStr()
                + "&WIDTH=" + _width.ToString()
                + "&HEIGHT=" + _height.ToString()
                + "&FORMAT=" + WMSImageFormatToString(_format)
                + "&TRANSPARENT=" + _transparent.ToString().ToUpper()
                + "&BGCOLOR=" + _bgcolor
                + CreateOtherStr()
                ;

            Uri reqUri = new Uri(uriString);
            return reqUri;
        }

        string checkMandatoryParams()
        {
            string problemParams = "";
            if (_requestUri == null)
            {
                problemParams += "RequestUri ";
            }
            if (_version == null)
            {
                problemParams += "Version ";
            }
            if (_layers.Count == 0)
            {
                problemParams += "Layers ";
            }
            if (_bbox.IsNull())
            {
                problemParams += "Bbox ";
            }
            if (_width == 0 )
            {
                problemParams += "Width ";
            }
            if (_height == 0)
            {
                problemParams += "Height ";
            }
            return problemParams;
        }

        string CreateCommaParam(List<string> paramList)
        {
            string sepStr = "";
            foreach (string p in paramList)
            {
                if (sepStr == "")
                {
                    sepStr = p;
                }
                else
                {
                    sepStr += "," + p;
                }
            }
            return sepStr;
        }

        string CreateBboxStr()
        {
            return
                _bbox.MinX.ToString() + "," +
                _bbox.MinY.ToString() + "," +
                _bbox.MaxX.ToString() + "," +
                _bbox.MaxY.ToString();
        }

        string CreateCrsStr()
        {
            string crsOrSrs;
            if (_version == WMSVersion.V1_3_0)
            {
                crsOrSrs = "CRS";
            }
            else
            {
                crsOrSrs = "SRS";
            }
            return crsOrSrs;
        }

        string CreateOtherStr()
        {
            string otherStr = "";
            foreach (KeyValuePair<string, string> keyAndValue in _otherParams)
            {
                otherStr += "&" + keyAndValue.Key + "=" + keyAndValue.Value;
            }
            return otherStr;
        }

        string GetWMSVersionString(WMSVersion version)
        {
            string res = "";
            switch (version)
            {
                case WMSVersion.V1_1:
                    res = "1.1";
                    break;
                case WMSVersion.V1_1_1:
                    res = "1.1.1";
                    break;
                case WMSVersion.V1_3_0:
                    res = "1.3.0";
                    break;
            }
            return res;
        }

        string WMSImageFormatToString(WMSImageFormat format)
        {
            string res = "";
            switch (format)
            {
                case WMSImageFormat.JPEG:
                    res = "image/jpeg";
                    break;
                case WMSImageFormat.PNG:
                    res = "image/png";
                    break;
            }
            return res;
        }

    }

    public enum WMSVersion
    {
        V1_1,
        V1_1_1,
        V1_3_0,
    }

    /// <summary>
    /// Silverlight supports PNG and JPEG only.
    /// </summary>
    public enum WMSImageFormat
    {
        PNG,
        JPEG,
    }
}
